﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Autodesk.Revit.DB;
using YJKRevitKernel.RevitDimensionUtility;

namespace YJKPatternSign.StairsRoomPlanSign.ModelLayer
{
	public class DimensionInformensionBean : IDimensionMake
	{
		public List<string> LstReplacedText
		{
			get
			{
				return this.m_lstReplacedText;
			}
			set
			{
				this.m_lstReplacedText = value;
			}
		}

		public List<XYZ> LstDimensionPoints
		{
			get
			{
				return this.m_lstDimensionPoints;
			}
			private set
			{
				this.m_lstDimensionPoints = value;
			}
		}

		public DimensionInformensionBean(Line inputBaseLine, List<XYZ> inputDimensionPoints, List<string> lstInputReplaceString = null)
		{
			this.m_dimensionBaseLine = inputBaseLine;
			this.LstDimensionPoints.AddRange(inputDimensionPoints);
			if (lstInputReplaceString != null)
			{
				this.LstReplacedText.AddRange(lstInputReplaceString);
			}
		}

		public bool TryMakeSign(Autodesk.Revit.DB.Document inputDoc, ViewPlan useView)
		{
			bool result;
			try
			{
				this.MakeProjectPoints();
				this.MakeUseLines();
				this.MakeDimension(inputDoc, useView);
				this.ChangeText();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public override bool Equals(object obj)
		{
			if (obj == null || !(obj is DimensionInformensionBean))
			{
				return false;
			}
			DimensionInformensionBean dimensionInformensionBean = obj as DimensionInformensionBean;
			this.MakeProjectPoints();
			dimensionInformensionBean.MakeProjectPoints();
			if (!this.m_dimensionBaseLine.Direction.IsAlmostEqualTo(dimensionInformensionBean.m_dimensionBaseLine.Direction, CmdStairsRoomPlanSign.NearTolerance) || this.LstDimensionPoints.Count != dimensionInformensionBean.LstDimensionPoints.Count || this.LstReplacedText.Count != dimensionInformensionBean.LstReplacedText.Count)
			{
				return false;
			}
			Line dimensionBaseLine = this.m_dimensionBaseLine;
			dimensionBaseLine.MakeUnbound();
			for (int i = 0; i < dimensionInformensionBean.LstDimensionPoints.Count; i++)
			{
				if (!dimensionBaseLine.Project(dimensionInformensionBean.LstDimensionPoints[i]).XYZPoint.IsAlmostEqualTo(this.m_lstProjectedPointsOnBaseLine[i], CmdStairsRoomPlanSign.NearTolerance))
				{
					return false;
				}
			}
			for (int j = 0; j < dimensionInformensionBean.LstReplacedText.Count; j++)
			{
				if (this.CheckStringNull(dimensionInformensionBean, j))
				{
					return false;
				}
				if (!dimensionInformensionBean.LstReplacedText[j].Equals(this.LstReplacedText[j]))
				{
					return false;
				}
			}
			return true;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		private bool CheckStringNull(DimensionInformensionBean inputBean, int indexOfReplace)
		{
			return (inputBean.LstReplacedText[indexOfReplace] != null || this.LstReplacedText[indexOfReplace] != null) && (inputBean.LstReplacedText[indexOfReplace] == null || this.LstReplacedText[indexOfReplace] == null);
		}

		private void MakeDimension(Autodesk.Revit.DB.Document inputDoc, ViewPlan useView)
		{
			ReferenceArray referenceArray = new ReferenceArray();
			foreach (Line line in this.m_lstLineForDimension)
			{
				this.m_lstAllMakedDetailLine.Add(inputDoc.Create.NewDetailCurve(useView, line) as DetailLine);
				referenceArray.Append(this.m_lstAllMakedDetailLine[this.m_lstAllMakedDetailLine.Count - 1].GeometryCurve.Reference);
			}
			DimensionType dimensionType = this.FindWantDimensionType(inputDoc);
			if (dimensionType != null)
			{
				this.m_makedDimension = inputDoc.Create.NewDimension(useView, this.m_dimensionBaseLine, referenceArray, dimensionType);
				return;
			}
			this.m_makedDimension = inputDoc.Create.NewDimension(useView, this.m_dimensionBaseLine, referenceArray);
		}

		private void MakeUseLines()
		{
			this.m_lstLineForDimension = new List<Line>();
			if (this.m_lstProjectedPointsOnBaseLine.Count > 1)
			{
				foreach (XYZ xyz in this.m_lstProjectedPointsOnBaseLine)
				{
					this.m_lstLineForDimension.Add(Line.CreateBound(xyz, xyz.Add(-this.m_useMakeLineDriection.Multiply(StaticResource.LineLengthForDimesion))));
				}
			}
		}

		private void MakeProjectPoints()
		{
			this.m_lstProjectedPointsOnBaseLine = new List<XYZ>();
			this.m_useMakeLineDriection = Utility.GetAVerticalVector(this.m_dimensionBaseLine.Direction, false);
			Line tempBaseUnboundLine = this.m_dimensionBaseLine.Clone() as Line;
			tempBaseUnboundLine.MakeUnbound();
			List<XYZ> list = new List<XYZ>();
			foreach (XYZ xyz in this.LstDimensionPoints)
			{
				list.Add(tempBaseUnboundLine.Project(xyz).XYZPoint);
			}
            var list2 = from k in list
			orderby(tempBaseUnboundLine.Project(k).Parameter)
			select k;
            list = list2.Distinct(new XYZCompare()).ToList<XYZ>();
			this.m_lstProjectedPointsOnBaseLine.AddRange(list);
		}

		private void ChangeText()
		{
			if (this.m_makedDimension != null)
			{
				DimensionSegmentArray segments = this.m_makedDimension.Segments;
				if (segments.Size == 0 && 0 < this.LstReplacedText.Count && this.LstReplacedText[0] != null)
				{
					this.m_makedDimension.ValueOverride = this.LstReplacedText[0];
				}
				for (int i = 0; i < segments.Size; i++)
				{
					if (i < this.LstReplacedText.Count - 1 && this.LstReplacedText[i] != null)
					{
						segments.get_Item(i).ValueOverride = this.LstReplacedText[i];
					}
				}
			}
		}

		private DimensionType FindWantDimensionType(Autodesk.Revit.DB.Document m_doc)
		{
			DimensionType result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(m_doc);
			DimensionType dimensionType = RevitDimensionUtiltyMethod.GetDimensionType(m_doc, DimensionTypeEnum.ScaleDimension, null);
			if (dimensionType != null)
			{
				result = dimensionType;
				return result;
			}
			foreach (Element element in filteredElementCollector.OfClass(typeof(DimensionType)))
			{
				DimensionType dimensionType2 = (DimensionType)element;
				if (dimensionType2 != null && Regex.IsMatch(dimensionType2.Name, StaticResource.Str_DimensionTypeName))
				{
					result = dimensionType2;
					break;
				}
			}
			return result;
		}

		private Line m_dimensionBaseLine;

		private List<XYZ> m_lstDimensionPoints = new List<XYZ>();

		private List<XYZ> m_lstProjectedPointsOnBaseLine = new List<XYZ>();

		private List<Line> m_lstLineForDimension = new List<Line>();

		private List<string> m_lstReplacedText = new List<string>();

		private XYZ m_useMakeLineDriection;

		private List<DetailLine> m_lstAllMakedDetailLine = new List<DetailLine>();

		private Dimension m_makedDimension;
	}
}
